import json
import sys
import datetime
import random
import serial.tools.list_ports
from PyQt6.QtWidgets import (
    QApplication, QWidget, QVBoxLayout, QHBoxLayout, QListWidget,
    QPushButton, QLabel, QSpinBox, QTableWidget, QTableWidgetItem,
    QHeaderView, QAbstractItemView, QMessageBox, QComboBox
)
from PyQt6.QtGui import QPixmap, QPainter, QFont, QColor
from PyQt6.QtCore import Qt, QRectF
from dither import dither_image, send_to_printer

class PosApp(QWidget):
    def __init__(self):
        super().__init__()
        with open('./data/takeout.json', encoding='utf-8') as f:
            rows = json.load(f)
        self.menu_items = {row['name']:row['price'] for row in rows};
        self.order_items = {}
        self.total_price = 0.0
        self.initUI()

    def initUI(self):
        self.setWindowTitle('快递面单机')
        self.setGeometry(100, 100, 1000, 800)  # 放大窗口尺寸

        # 主布局
        main_layout = QHBoxLayout()

        # 左侧布局（菜单）
        left_layout = QVBoxLayout()
        menu_label = QLabel("订单")
        menu_label.setStyleSheet("font-size: 18px; font-weight: bold;")

        self.menu_list = QListWidget()
        self.menu_list.addItems(self.menu_items.keys())
        self.menu_list.setStyleSheet("font-size: 16px;")
        self.menu_list.setMinimumWidth(300)  # 设置最小宽度

        # 数量选择和添加按钮布局
        quantity_layout = QHBoxLayout()
        quantity_label = QLabel("数量:")
        quantity_label.setStyleSheet("font-size: 16px;")

        self.quantity_spinbox = QSpinBox()
        self.quantity_spinbox.setRange(1, 99)
        self.quantity_spinbox.setValue(1)
        self.quantity_spinbox.setStyleSheet("font-size: 16px;")

        add_button = QPushButton("添加到订单")
        add_button.setStyleSheet("font-size: 16px; padding: 8px;")
        add_button.clicked.connect(self.addItemToOrder)

        quantity_layout.addWidget(quantity_label)
        quantity_layout.addWidget(self.quantity_spinbox)
        quantity_layout.addWidget(add_button)

        left_layout.addWidget(menu_label)
        left_layout.addWidget(self.menu_list)
        left_layout.addLayout(quantity_layout)

        # 右侧布局（订单）
        right_layout = QVBoxLayout()
        order_label = QLabel("当前订单")

        # 订单表格
        self.order_table = QTableWidget()
        self.order_table.setColumnCount(4)
        self.order_table.setHorizontalHeaderLabels(["商品名称", "数量", "单价", "小计"])
        self.order_table.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers)
        self.order_table.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
        self.order_table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.Stretch)

        # 总计布局
        total_layout = QHBoxLayout()
        total_label = QLabel("总计:")
        self.total_label_value = QLabel("￥ 0.00")
        self.total_label_value.setStyleSheet("font-size: 16px; font-weight: bold;")
        total_layout.addWidget(total_label)
        total_layout.addStretch()
        total_layout.addWidget(self.total_label_value)

        # 串口选择布局
        serial_layout = QHBoxLayout()
        serial_label = QLabel("串口:")
        self.serial_combo = QComboBox()
        refresh_button = QPushButton("🔄")
        refresh_button.setFixedSize(30, 30)
        refresh_button.clicked.connect(self.refreshSerialPorts)

        serial_layout.addWidget(serial_label)
        serial_layout.addWidget(self.serial_combo)
        serial_layout.addWidget(refresh_button)
        serial_layout.addStretch()

        # 操作按钮布局
        button_layout = QHBoxLayout()
        clear_button = QPushButton("清空订单")
        print_button = QPushButton("确认下单")
        clear_button.setStyleSheet("padding: 8px 15px; background-color: #f44336; color: white;")
        print_button.setStyleSheet("padding: 8px 15px; background-color: #4CAF50; color: white;")

        clear_button.clicked.connect(self.clearOrder)
        print_button.clicked.connect(self.generateOrder)

        button_layout.addStretch()
        button_layout.addLayout(serial_layout)
        button_layout.addWidget(clear_button)
        button_layout.addWidget(print_button)

        # 添加所有组件到右侧布局
        right_layout.addWidget(order_label)
        right_layout.addWidget(self.order_table)
        right_layout.addLayout(total_layout)
        right_layout.addLayout(button_layout)

        # 设置主布局的比例
        main_layout.addLayout(left_layout, 1)
        main_layout.addLayout(right_layout, 2)

        self.setLayout(main_layout)
        self.updateSerialPorts()

    def updateSerialPorts(self):
        self.serial_combo.clear()
        ports = serial.tools.list_ports.comports()
        if ports:
            for port in ports:
                self.serial_combo.addItem(f"{port.device} ({port.description})")
        else:
            self.serial_combo.addItem("未检测到串口")

    def refreshSerialPorts(self):
        self.updateSerialPorts()

    def addItemToOrder(self):
        selected_items = self.menu_list.selectedItems()
        if not selected_items:
            QMessageBox.warning(self, "提示", "请先从菜单中选择一个商品！")
            return

        item_name = selected_items[0].text()
        price = self.menu_items[item_name]
        quantity = self.quantity_spinbox.value()

        if item_name in self.order_items:
            self.order_items[item_name]['quantity'] += quantity
        else:
            self.order_items[item_name] = {'price': price, 'quantity': quantity}

        self.updateOrderTable()
        self.updateTotal()
        self.quantity_spinbox.setValue(1)

    def updateOrderTable(self):
        self.order_table.setRowCount(len(self.order_items))
        for row, (name, details) in enumerate(self.order_items.items()):
            price = details['price']
            quantity = details['quantity']
            subtotal = price * quantity

            self.order_table.setItem(row, 0, QTableWidgetItem(name))
            self.order_table.setItem(row, 1, QTableWidgetItem(str(quantity)))
            self.order_table.setItem(row, 2, QTableWidgetItem(f"￥{price:.2f}"))
            self.order_table.setItem(row, 3, QTableWidgetItem(f"￥{subtotal:.2f}"))

    def updateTotal(self):
        self.total_price = sum(details['price'] * details['quantity'] for details in self.order_items.values())
        self.total_label_value.setText(f"￥ {self.total_price:.2f}")

    def clearOrder(self):
        reply = QMessageBox.question(self, '确认', '确定要清空当前订单吗?',
                                   QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No)
        if reply == QMessageBox.StandardButton.Yes:
            self.order_items = {}
            self.updateOrderTable()
            self.updateTotal()

    def generateOrder(self):
        if not self.order_items:
            QMessageBox.warning(self, "提示", "订单为空，无法生成！")
            return

        selected_port = self.serial_combo.currentText().split()[0]
        if not selected_port:
            QMessageBox.warning(self, "提示", "请先选择打印机串口！")
            return

        try:
            order_id = datetime.datetime.now().strftime('%Y%m%d%H%M') + str(random.randint(1000, 9999))
            order_time = datetime.datetime.now()
            filepath = f"order_{order_id}.png"
            self.createReceiptImage(filepath, order_id, order_time)

            processed_img = dither_image(filepath, f"processed_{filepath}")
            send_to_printer(processed_img, port=selected_port)

            self.order_items = {}
            self.updateOrderTable()
            self.updateTotal()

            QMessageBox.information(self, "成功", "订单已生成并发送至打印机！")

        except Exception as e:
            QMessageBox.critical(self, "错误", f"打印订单时发生错误：{str(e)}")

    def createReceiptImage(self, filepath, order_id, order_time):
        receipt_width = 384
        padding = 15
        line_height = {
            'normal': 60,    # 增加普通文本的行高
            'small': 60,     # 增加订单信息的行高
            'title': 80,     # 增加标题的行高
            'header': 60     # 增加表头的行高
        }

        # 计算总高度
        current_y = padding
        current_y += line_height['title'] + 5  # 标题
        current_y += line_height['small']      # 订单号
        current_y += line_height['small'] + 5  # 时间
        current_y += 10                        # 分隔线
        current_y += line_height['header']     # 表头
        current_y += 5                         # 间距
        current_y += len(self.order_items) * line_height['normal']  # 商品列表
        current_y += 10                        # 分隔线
        current_y += line_height['normal']     # 总计
        current_y += padding                   # 底部间距

        receipt_height = int(current_y)

        # 创建图片
        pixmap = QPixmap(receipt_width, receipt_height)
        pixmap.fill(QColor("white"))
        painter = QPainter(pixmap)
        painter.setRenderHint(QPainter.RenderHint.Antialiasing)

        # 设置字体
        fonts = {
            'title': QFont("黑体", 24, QFont.Weight.Bold),  # 标题字体加大
            'normal': QFont("宋体", 14),                    # 普通文本字体加大
            'small': QFont("宋体", 14),                    # 订单信息字体加大
            'header': QFont("宋体", 16, QFont.Weight.Bold)  # 表头字体加大
        }

        current_y = padding

        # 绘制标题
        painter.setFont(fonts['title'])
        title_rect = QRectF(0, current_y, receipt_width, line_height['title'])
        painter.drawText(title_rect, Qt.AlignmentFlag.AlignCenter, "11111")
        current_y += line_height['title'] + 5

        # 绘制订单信息
        painter.setFont(fonts['small'])
        painter.drawText(padding, current_y, f"订单编号: {order_id}")
        current_y += line_height['small']
        painter.drawText(padding, current_y, f"订单时间: {order_time.strftime('%Y-%m-%d %H:%M:%S')}")
        current_y += line_height['small'] + 5

        # 绘制分隔线
        painter.setPen(Qt.GlobalColor.gray)
        painter.drawLine(padding, current_y, receipt_width - padding, current_y)
        current_y += 10
        painter.setPen(Qt.GlobalColor.black)

        # 调整列位置，增加间距
        col_positions = {
            'name': padding,
            'quantity': receipt_width * 0.45,    # 数量列左移
            'price': receipt_width * 0.60,      # 单价列左移
            'subtotal': receipt_width * 0.75    # 小计列左移
        }

        # 设置每列的宽度
        col_widths = {
            'name': col_positions['quantity'] - col_positions['name'] - 10,
            'quantity': col_positions['price'] - col_positions['quantity'] - 10,
            'price': col_positions['subtotal'] - col_positions['price'] - 10,
            'subtotal': receipt_width - col_positions['subtotal'] - padding
        }

        # 绘制表头
        painter.setFont(fonts['header'])
        col_positions = {
            'name': padding,
            'quantity': receipt_width * 0.45,    # 数量列左移
            'price': receipt_width * 0.60,      # 单价列左移
            'subtotal': receipt_width * 0.75    # 小计列左移
        }

        # 设置每列的宽度
        col_widths = {
            'name': col_positions['quantity'] - col_positions['name'] - 10,
            'quantity': col_positions['price'] - col_positions['quantity'] - 10,
            'price': col_positions['subtotal'] - col_positions['price'] - 10,
            'subtotal': receipt_width - col_positions['subtotal'] - padding
        }

        painter.drawText(int(col_positions['name']), current_y, "商品名称")
        painter.drawText(int(col_positions['quantity']), current_y, "数量")
        painter.drawText(int(col_positions['price']), current_y, "单价")
        painter.drawText(int(col_positions['subtotal']), current_y, "小计")
        current_y += line_height['header'] + 5

        # 绘制商品列表
        painter.setFont(fonts['normal'])
        for name, details in self.order_items.items():
            price = details['price']
            quantity = details['quantity']
            subtotal = price * quantity

            # 使用QRectF来控制文本区域
            name_rect = QRectF(col_positions['name'], current_y, col_widths['name'], line_height['normal'])
            qty_rect = QRectF(col_positions['quantity'], current_y, col_widths['quantity'], line_height['normal'])
            price_rect = QRectF(col_positions['price'], current_y, col_widths['price'], line_height['normal'])
            subtotal_rect = QRectF(col_positions['subtotal'], current_y, col_widths['subtotal'], line_height['normal'])

            painter.drawText(name_rect, Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter, name)
            painter.drawText(qty_rect, Qt.AlignmentFlag.AlignCenter | Qt.AlignmentFlag.AlignVCenter, str(quantity))
            painter.drawText(price_rect, Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter, f"￥{price:.2f}")
            painter.drawText(subtotal_rect, Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter, f"￥{subtotal:.2f}")

            current_y += line_height['normal']

        # 绘制分隔线
        painter.setPen(Qt.GlobalColor.gray)
        painter.drawLine(padding, current_y, receipt_width - padding, current_y)
        current_y += 10
        painter.setPen(Qt.GlobalColor.black)

        # 绘制总计
        painter.setFont(fonts['header'])
        total_text = f"总计: ￥{self.total_price:.2f}"
        total_rect = QRectF(padding, current_y, receipt_width - 2 * padding, line_height['normal'])
        painter.drawText(total_rect, Qt.AlignmentFlag.AlignRight, total_text)

        painter.end()
        pixmap.save(filepath, "PNG")

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = PosApp()
    ex.show()
    sys.exit(app.exec())